home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gstype2.c < prev    next >
C/C++ Source or Header  |  1997-03-23  |  17KB  |  639 lines

  1. /* Copyright (C) 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gstype2.c */
  20. /* Adobe Type 2 charstring interpreter */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsstruct.h"
  26. #include "gxarith.h"
  27. #include "gxfixed.h"
  28. #include "gxmatrix.h"
  29. #include "gxcoord.h"
  30. #include "gxistate.h"
  31. #include "gzpath.h"
  32. #include "gxchar.h"
  33. #include "gxfont.h"
  34. #include "gxfont1.h"
  35. #include "gxtype1.h"
  36.  
  37. /* NOTE: The following are not yet implemented:
  38.  *    Registry items other than 0
  39.  *    Hint and counter masks (but they are parsed correctly)
  40.  *    'random' operator
  41.  */
  42.  
  43. /* Define a pointer to the charstring interpreter stack. */
  44. typedef fixed _ss *cs_ptr;
  45.  
  46. /* ------ Internal routines ------ */
  47.  
  48. /*
  49.  * Set the character width.  This is provided as an optional extra operand
  50.  * on the stack for the first operator.  After setting the width, we remove
  51.  * the extra operand, and back up the interpreter pointer so we will
  52.  * re-execute the operator when control re-enters the interpreter.
  53.  */
  54. #define check_first_operator(explicit_width)\
  55.   do {\
  56.     if ( pcis->init_done < 0 )\
  57.       { ipsp->ip = cip, ipsp->dstate = state;\
  58.     return type2_sbw(pcis, csp, cstack, ipsp, explicit_width);\
  59.       }\
  60.   } while (0)
  61. private int near
  62. type2_sbw(gs_type1_state *pcis, cs_ptr csp, cs_ptr cstack, ip_state *ipsp,
  63.   bool explicit_width)
  64. {    fixed wx;
  65.  
  66.     if ( explicit_width )
  67.       { wx = cstack[0] + pcis->pfont->data.nominalWidthX;
  68.         memmove(cstack, cstack + 1, (csp - cstack) * sizeof(*cstack));
  69.         --csp;
  70.       }
  71.     else
  72.       wx = pcis->pfont->data.defaultWidthX;
  73.     gs_type1_sbw(pcis, fixed_0, fixed_0, wx, fixed_0);
  74.     /* Back up the interpretation pointer. */
  75.     { ip_state *ipsp = &pcis->ipstack[pcis->ips_count - 1];
  76.       ipsp->ip--;
  77.       decrypt_skip_previous(*ipsp->ip, ipsp->dstate);
  78.     }
  79.     /* Save the interpreter state. */
  80.     pcis->os_count = csp + 1 - cstack;
  81.     pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
  82.     if ( pcis->init_done < 0 )
  83.       {    /* Finish init when we return. */
  84.         pcis->init_done = 0;
  85.       }
  86.     return type1_result_sbw;
  87. }
  88.  
  89. /* ------ Main interpreter ------ */
  90.  
  91. /*
  92.  * Continue interpreting a Type 2 charstring.  If str != 0, it is taken as
  93.  * the byte string to interpret.  Return 0 on successful completion, <0 on
  94.  * error, or >0 when client intervention is required (or allowed).  The int*
  95.  * argument is only for compatibility with the Type 1 charstring interpreter.
  96.  */
  97. private int
  98. gs_type2_charstring_interpret(gs_type1_state *pcis,
  99.   const gs_const_string *str, int *ignore_pindex)
  100. {    gs_font_type1 *pfont = pcis->pfont;
  101.     gs_type1_data *pdata = &pfont->data;
  102.     bool encrypted = pdata->lenIV >= 0;
  103.     gs_op1_state s;
  104.     fixed cstack[ostack_size];
  105.     cs_ptr csp;
  106. #define clear csp = cstack - 1
  107.     ip_state *ipsp = &pcis->ipstack[pcis->ips_count - 1];
  108.     register const byte *cip;
  109.     register crypt_state state;
  110.     register int c;
  111.     cs_ptr ap;
  112.     bool vertical;
  113.     int code = 0;
  114.     /****** FAKE THE REGISTRY ******/
  115.     struct { float *values; uint size; } Registry[1];
  116.     Registry[0].values = pcis->pfont->data.WeightVector.values;
  117.  
  118.     switch ( pcis->init_done )
  119.       {
  120.       case -1:
  121.         break;
  122.       case 0: 
  123.         gs_type1_finish_init(pcis, &s);  /* sets sfc, ptx, pty, origin */
  124.         break;
  125.       default /*case 1*/:
  126.         ptx = pcis->position.x;
  127.         pty = pcis->position.y;
  128.         sfc = pcis->fc;
  129.       }
  130.     sppath = pcis->path;
  131.     s.pcis = pcis;
  132.     init_cstack(cstack, csp, pcis);
  133.  
  134.     if ( str == 0 )
  135.       goto cont;
  136.     ipsp->char_string = *str;
  137.     cip = str->data;
  138. call:    state = crypt_charstring_seed;
  139.     if ( encrypted )
  140.        {    int skip = pdata->lenIV;
  141.         /* Skip initial random bytes */
  142.         for ( ; skip > 0; ++cip, --skip )
  143.           decrypt_skip_next(*cip, state);
  144.        }
  145.     goto top;
  146. cont:    cip = ipsp->ip;
  147.     state = ipsp->dstate;
  148. top:    for ( ; ; )
  149.      { uint c0 = *cip++;
  150.  
  151.        charstring_next(c0, state, c, encrypted);
  152.        if ( c >= c_num1 )
  153.          {
  154.            /* This is a number, decode it and push it on the stack. */
  155.  
  156.            if ( c < c_pos2_0 )
  157.          {                /* 1-byte number */
  158.            decode_push_num1(csp, c);
  159.          }
  160.            else if ( c < cx_num4 )
  161.          {                /* 2-byte number */
  162.            decode_push_num2(csp, c, cip, state, encrypted);
  163.          }
  164.            else if ( c == cx_num4 )
  165.          {                /* 4-byte number */
  166.            long lw;
  167.  
  168.            decode_num4(lw, cip, state, encrypted);
  169.            /* 32-bit numbers are 16:16. */
  170.            *++csp = arith_rshift(lw, 16 - _fixed_shift);
  171.          }
  172.            else            /* not possible */
  173.          return_error(gs_error_invalidfont);
  174. pushed:           if_debug3('1', "[1]%d: (%d) %f\n",
  175.              (int)(csp - cstack), c, fixed2float(*csp));
  176.            continue;
  177.          }
  178.  
  179. #ifdef DEBUG
  180.        if ( gs_debug['1'] )
  181.          { static const char *c2names[] =
  182.             { char2_command_names };
  183.            if ( c2names[c] == 0 )
  184.          dprintf2("[1]0x%lx: %02x??\n", (ulong)(cip - 1), c);
  185.            else
  186.          dprintf3("[1]0x%lx: %02x %s\n", (ulong)(cip - 1), c,
  187.               c2names[c]);
  188.          }
  189. #endif
  190.        switch ( (char_command)c )
  191.          {
  192. #define cnext clear; goto top
  193.  
  194.         /* Commands with identical functions in Type 1 and Type 2, */
  195.         /* except for 'escape'. */
  196.  
  197.     case c_undef0:
  198.     case c_undef2:
  199.     case c_undef17:
  200.         return_error(gs_error_invalidfont);
  201.     case c_callsubr:
  202.         c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
  203.         code = (*pdata->subr_proc)
  204.           (pfont, c, false, &ipsp[1].char_string);
  205. subr:        if ( code < 0 )
  206.           return_error(code);
  207.         --csp;
  208.         ipsp->ip = cip, ipsp->dstate = state;
  209.         ++ipsp;
  210.         cip = ipsp->char_string.data;
  211.         goto call;
  212.     case c_return:
  213.         --ipsp;
  214.         goto cont;
  215.     case c_undoc15:
  216.         /* See gstype1.h for information on this opcode. */
  217.         cnext;
  218.         
  219.         /* Commands with similar but not identical functions */
  220.         /* in Type 1 and Type 2 charstrings. */
  221.  
  222.     case cx_hstem:
  223.         goto hstem;
  224.     case cx_vstem:
  225.         goto vstem;
  226.     case cx_vmoveto:
  227.         check_first_operator(csp > cstack);
  228.         accum_y(*csp);
  229. move:        if ( (pcis->hint_next != 0 || path_is_drawing(sppath)) )
  230.           apply_path_hints(pcis, true);
  231.         code = gx_path_add_point(sppath, ptx, pty);
  232. cc:        if ( code < 0 )
  233.           return code;
  234.         goto pp;
  235.     case cx_rlineto:
  236.         for ( ap = cstack; ap + 1 <= csp; ap += 2 )
  237.           { accum_xy(ap[0], ap[1]);
  238.             code = gx_path_add_line(sppath, ptx, pty);
  239.             if ( code < 0 )
  240.               return code;
  241.           }
  242. pp:        if_debug2('1', "[1]pt=(%g,%g)\n",
  243.               fixed2float(ptx), fixed2float(pty));
  244.         cnext;
  245.     case cx_hlineto:
  246.         vertical = false;
  247.         goto hvl;
  248.     case cx_vlineto:
  249.         vertical = true;
  250. hvl:        for ( ap = cstack; ap <= csp; vertical = !vertical, ++ap )
  251.           { if ( vertical )
  252.               accum_y(*ap);
  253.             else
  254.               accum_x(*ap);
  255.             code = gx_path_add_line(sppath, ptx, pty);
  256.             if ( code < 0 )
  257.               return code;
  258.               }
  259.         goto pp;
  260.     case cx_rrcurveto:
  261. rrc:        for ( ap = cstack; ap + 5 <= csp; ap += 6 )
  262.           { code = gs_op1_rrcurveto(&s, ap[0], ap[1], ap[2],
  263.                         ap[3], ap[4], ap[5]);
  264.             if ( code < 0 )
  265.               return code;
  266.           }
  267.         goto pp;
  268.     case cx_endchar:
  269.         /*
  270.          * This might be the only operator in the charstring.
  271.          * In this case, there might be a width on the stack.
  272.          */
  273.         check_first_operator(csp >= cstack);
  274.         return gs_type1_endchar(pcis);
  275.     case cx_rmoveto:
  276.         check_first_operator(csp > cstack + 1);
  277.         accum_xy(csp[-1], *csp);
  278.         goto move;
  279.     case cx_hmoveto:
  280.         check_first_operator(csp > cstack);
  281.         accum_x(*csp);
  282.         goto move;
  283.     case cx_vhcurveto:
  284.         vertical = true;
  285.         goto hvc;
  286.     case cx_hvcurveto:
  287.         vertical = false;
  288. hvc:        for ( ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4 )
  289.           { gs_fixed_point pt1, pt2;
  290.             fixed ax0 = sppath->position.x - ptx;
  291.             fixed ay0 = sppath->position.y - pty;
  292.  
  293.             if ( vertical )
  294.               accum_y(ap[0]);
  295.             else
  296.               accum_x(ap[0]);
  297.             pt1.x = ptx + ax0, pt1.y = pty + ay0;
  298.             accum_xy(ap[1], ap[2]);
  299.             pt2.x = ptx, pt2.y = pty;
  300.             if ( vertical )
  301.               { if ( ap + 4 == csp )
  302.               accum_xy(ap[3], ap[4]);
  303.             else
  304.               accum_x(ap[3]);
  305.               }
  306.             else
  307.               { if ( ap + 4 == csp )
  308.               accum_xy(ap[4], ap[3]);
  309.             else
  310.               accum_y(ap[3]);
  311.               }
  312.             code =  gx_path_add_curve(sppath, pt1.x, pt1.y,
  313.                           pt2.x, pt2.y, ptx, pty);
  314.             if ( code < 0 )
  315.               return code;
  316.           }
  317.         goto pp;
  318.  
  319.             /***********************
  320.              * New Type 2 commands *
  321.              ***********************/
  322.  
  323.     case c2_blend:
  324.         { int n = fixed2int_var(*csp);
  325.           int num_values = csp - cstack;
  326.           gs_font_type1 *pfont = pcis->pfont;
  327.           int k = pfont->data.WeightVector.count;
  328.           int i, j;
  329.           cs_ptr base, deltas;
  330.  
  331.           base = csp - 1 - num_values;
  332.           deltas = base + n - 1;
  333.           for ( j = 0; j < n; j++, base++, deltas += k - 1 )
  334.             for ( i = 1; i < k; i++ )
  335.               *base += deltas[i] * pfont->data.WeightVector.values[i];
  336.         }
  337.         cnext;
  338.     case c2_hstemhm:
  339.         pcis->have_hintmask = true;
  340. hstem:        check_first_operator(!((csp - cstack) & 1));
  341.         apply_path_hints(pcis, false);
  342.         { fixed x = 0;
  343.  
  344.           for ( ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2 )
  345.             type1_hstem(pcis, x += ap[0], ap[1]);
  346.         }
  347.         cnext;
  348.     case c2_hintmask:
  349.         /* (falls through) */
  350.     case c2_cntrmask:
  351.         { byte mask[max_total_stem_hints / 8];
  352.           int i;
  353.  
  354.           for ( i = 0;
  355.             i < pcis->vstem_hints.count + pcis->hstem_hints.count;
  356.             ++cip, i += 8
  357.               )
  358.             charstring_next(*cip, state, mask[i >> 3], encrypted);
  359.           ipsp->ip = cip;
  360.           ipsp->dstate = state;
  361.         }
  362.         /****** NYI ******/
  363.         break;
  364.     case c2_vstemhm:
  365.         pcis->have_hintmask = true;
  366. vstem:        check_first_operator(!((csp - cstack) & 1));
  367.         apply_path_hints(pcis, false);
  368.         { fixed x = 0;
  369.  
  370.           for ( ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2 )
  371.             type1_vstem(pcis, x += ap[0], ap[1]);
  372.         }
  373.         cnext;
  374.     case c2_rcurveline:
  375.         for ( ap = cstack; ap + 5 <= csp; ap += 6 )
  376.           { code = gs_op1_rrcurveto(&s, ap[0], ap[1], ap[2], ap[3],
  377.                         ap[4], ap[5]);
  378.             if ( code < 0 )
  379.               return code;
  380.           }
  381.         accum_xy(ap[0], ap[1]);
  382.         code = gx_path_add_line(sppath, ptx, pty);
  383.         goto cc;
  384.     case c2_rlinecurve:
  385.         for ( ap = cstack; ap + 7 <= csp; ap += 2 )
  386.           { accum_xy(ap[0], ap[1]);
  387.             code = gx_path_add_line(sppath, ptx, pty);
  388.             if ( code < 0 )
  389.               return code;
  390.           }
  391.         code = gs_op1_rrcurveto(&s, ap[0], ap[1], ap[2], ap[3],
  392.                     ap[4], ap[5]);
  393.         goto cc;
  394.     case c2_vvcurveto:
  395.         ap = cstack;
  396.         { int n = csp + 1 - cstack;
  397.           fixed dxa = (n & 1 ? *ap++ : 0);
  398.  
  399.           for ( ; ap + 3 <= csp; ap += 4 )
  400.             { code = gs_op1_rrcurveto(&s, dxa, ap[0], ap[1], ap[2],
  401.                           fixed_0, ap[3]);
  402.               if ( code < 0 )
  403.                 return code;
  404.               dxa = 0;
  405.             }
  406.         }
  407.         goto pp;
  408.     case c2_hhcurveto:
  409.         ap = cstack;
  410.         { int n = csp + 1 - cstack;
  411.           fixed dya = (n & 1 ? *ap++ : 0);
  412.  
  413.           for ( ; ap + 3 <= csp; ap += 4 )
  414.             { code = gs_op1_rrcurveto(&s, ap[0], dya, ap[1], ap[2],
  415.                           ap[3], fixed_0);
  416.               if ( code < 0 )
  417.                 return code;
  418.               dya = 0;
  419.             }
  420.         }
  421.         goto pp;
  422.     case c2_shortint:
  423.         { int c1, c2;
  424.  
  425.           charstring_next(*cip, state, c1, encrypted); ++cip;
  426.           charstring_next(*cip, state, c2, encrypted); ++cip;
  427.           *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2);
  428.         }
  429.         goto pushed;
  430.     case c2_callgsubr:
  431.         c = fixed2int_var(*csp) + pdata->gsubrNumberBias;
  432.         code = (*pdata->subr_proc)
  433.           (pfont, c, true, &ipsp[1].char_string);
  434.         goto subr;
  435.     case cx_escape:
  436.         charstring_next(*cip, state, c, encrypted); ++cip;
  437. #ifdef DEBUG
  438.         if ( gs_debug['1'] && c < char2_extended_command_count )
  439.           { static const char *ce2names[] =
  440.              { char2_extended_command_names };
  441.             if ( ce2names[c] == 0 )
  442.               dprintf2("[1]0x%lx: %02x??\n", (ulong)(cip - 1), c);
  443.             else
  444.               dprintf3("[1]0x%lx: %02x %s\n", (ulong)(cip - 1), c,
  445.                    ce2names[c]);
  446.           }
  447. #endif
  448.         switch ( (char2_extended_command)c )
  449.           {
  450.     case ce2_and:
  451.         csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0);
  452.         --csp; break;
  453.     case ce2_or:
  454.         csp[-1] = (csp[-1] | *csp ? fixed_1 : 0);
  455.         --csp; break;
  456.     case ce2_not:
  457.         *csp = (*csp ? 0 : fixed_1);
  458.         break;
  459.     case ce2_store:
  460.         { int i, n = fixed2int_var(*csp);
  461.           float *to = Registry[fixed2int_var(csp[-3])].values +
  462.             fixed2int_var(csp[-2]);
  463.           const fixed *from =
  464.             pcis->transient_array + fixed2int_var(csp[-1]);
  465.  
  466.           for ( i = 0; i < n; ++i )
  467.             to[i] = fixed2float(from[i]);
  468.         }
  469.         csp -= 4; break;
  470.     case ce2_abs:
  471.         if ( *csp < 0 )
  472.           *csp = -*csp;
  473.         break;
  474.     case ce2_add:
  475.         csp[-1] += *csp;
  476.         --csp; break;
  477.     case ce2_sub:
  478.         csp[-1] -= *csp;
  479.         --csp; break;
  480.     case ce2_div:
  481.         csp[-1] = float2fixed((double)csp[-1] / *csp);
  482.         --csp; break;
  483.     case ce2_load:
  484.          /* The specification says there is no j (starting index */
  485.          /* in registry array) argument.... */
  486.         { int i, n = fixed2int_var(*csp);
  487.           const float *from = Registry[fixed2int_var(csp[-2])].values;
  488.           fixed *to =
  489.             pcis->transient_array + fixed2int_var(csp[-1]);
  490.  
  491.           for ( i = 0; i < n; ++i )
  492.             to[i] = float2fixed(from[i]);
  493.         }
  494.         csp -= 3; break;
  495.     case ce2_neg:
  496.         *csp = -*csp;
  497.         break;
  498.     case ce2_eq:
  499.         csp[-1] = (csp[-1] == *csp ? fixed_1 : 0);
  500.         --csp; break;
  501.     case ce2_drop:
  502.         --csp; break;
  503.     case ce2_put:
  504.         pcis->transient_array[fixed2int_var(*csp)] = csp[-1];
  505.         csp -= 2; break;
  506.     case ce2_get:
  507.         *csp = pcis->transient_array[fixed2int_var(*csp)];
  508.         break;
  509.     case ce2_ifelse:
  510.         if ( csp[-1] > *csp )
  511.           csp[-3] = csp[-2];
  512.         csp -= 3; break;
  513.     case ce2_random:
  514.         ++csp;
  515.         /****** NYI ******/
  516.         break;
  517.     case ce2_mul:
  518.         { double prod = fixed2float(csp[-1]) * *csp;
  519.           csp[-1] =
  520.             (prod > max_fixed ? max_fixed :
  521.              prod < min_fixed ? min_fixed : prod);
  522.         }
  523.         --csp; break;
  524.     case ce2_sqrt:
  525.         if ( *csp >= 0 )
  526.           *csp = float2fixed(sqrt(fixed2float(*csp)));
  527.         break;
  528.     case ce2_dup:
  529.         csp[1] = *csp;
  530.         ++csp; break;
  531.     case ce2_exch:
  532.         { fixed top = *csp;
  533.           *csp = csp[-1], csp[-1] = top;
  534.         }
  535.         break;
  536.     case ce2_index:
  537.         *csp =
  538.           (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]);
  539.         break;
  540.     case ce2_roll:
  541.         { int j = fixed2int_var(*csp);
  542.           int n = fixed2int_var(csp[-1]);
  543.           cs_ptr bot;
  544.  
  545.           csp -= 2;
  546.           if ( n < 0 || n > csp + 1 - cstack )
  547.             return_error(gs_error_invalidfont);
  548.           if ( n == 0 )
  549.             break;
  550.           if ( j < 0 )
  551.             j = n - (-j % n);
  552.               bot = csp + 1 - n;
  553.           while ( --j >= 0 )
  554.             { fixed top = *bot;
  555.               memmove(bot, bot + 1, (n - 1) * sizeof(fixed));
  556.               *csp = top;
  557.             }
  558.         }
  559.         break;
  560.     case ce2_hflex:
  561.         csp[6] = fixed_half;        /* fd/100 */
  562.         csp[4] = 0, csp[5] = *csp;    /* dx6, dy6 */
  563.         csp[2] = 0, csp[3] = csp[-1];    /* dx5, dy5 */
  564.         *csp = 0, csp[1] = csp[-2];    /* dx4, dy4 */
  565.         csp[-2] = csp[-3], csp[-1] = 0;    /* dx3, dy3 */
  566.         csp[-3] = csp[-4], csp[-4] = csp[-5];    /* dx2, dy2 */
  567.         csp[-5] = 0;            /* dy1 */
  568.         csp += 6; goto flex;
  569.     case ce2_flex:
  570.         *csp /= 100;            /* fd/100 */
  571. flex:        { fixed x_join = csp[-12] + csp[-10] + csp[-8];
  572.           fixed y_join = csp[-11] + csp[-9] + csp[-7];
  573.           fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2];
  574.           fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1];
  575.           gs_point join, end;
  576.  
  577.           if ( (code = gs_distance_transform(fixed2float(x_join),
  578.                              fixed2float(y_join),
  579.                              &ctm_only(pcis->pis),
  580.                              &join)) < 0 ||
  581.                (code = gs_distance_transform(fixed2float(x_end),
  582.                              fixed2float(y_end),
  583.                              &ctm_only(pcis->pis),
  584.                              &end)) < 0
  585.              )
  586.             return code;
  587.           /*
  588.            * The distance from the point (U,V) from a line from
  589.            * (0,0) to (C,D) is
  590.            *    abs(C*V - D*U) / sqrt(C^2 + D^2)
  591.            * In this case (U,V) is join, and (C,D) is end.
  592.            */
  593.           if ( fabs(end.x * join.y - end.y * join.x) >=
  594.                  hypot(end.x, end.y) * fixed2float(*csp) )
  595.             { /* Do flex as curve. */
  596.               --csp;
  597.               goto rrc;
  598.             }
  599.           /* Do flex as line. */
  600.           accum_xy(x_end, y_end);
  601.           code = gx_path_add_line(sppath, ptx, pty);
  602.         }
  603.         cnext;
  604.     case ce2_hflex1:
  605.         csp[4] = fixed_half;        /* fd/100 */
  606.         csp[2] = *csp, csp[3] = 0;    /* dx6, dy6 */
  607.         *csp = csp[-2], csp[1] = csp[-1];    /* dx5, dy5 */
  608.         csp[-2] = csp[-3], csp[-1] = 0;    /* dx4, dy4 */
  609.         csp[-3] = 0;            /* dy3 */
  610.         csp += 4; goto flex;
  611.     case ce2_flex1:
  612.         { fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2];
  613.           fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1];
  614.  
  615.           if ( any_abs(dx) > any_abs(dy) )
  616.             csp[1] = -dy;        /* d6 is dx6 */
  617.           else
  618.             csp[1] = *csp, *csp = -dx;    /* d6 is dy6 */
  619.         }
  620.         csp[2] = fixed_half;        /* fd/100 */
  621.         csp += 2; goto flex;
  622.           }
  623.         break;
  624.  
  625.         /* Fill up the dispatch up to 32. */
  626.  
  627.     case_c2_undefs:
  628.     default:        /* pacify compiler */
  629.         return_error(gs_error_invalidfont);
  630.          }
  631.      }
  632. }
  633.  
  634. /* Register the interpreter. */
  635. void
  636. gs_gstype2_init(gs_memory_t *mem)
  637. {    gs_charstring_interpreter[2] = gs_type2_charstring_interpret;
  638. }
  639.